<template>
  <div class="merge-result">
    <div class="merge-head">
      <div class="head-left">
        <div class="head-title">{{ pageTitle }}</div>
        <el-button
          v-if="fusionStatus === 0 || fusionStatus === 2"
          type="text"
          @click="showPending"
        >
          <i class="el-icon-search"></i>
          查看全部待融合实体
        </el-button>
      </div>

      <div class="head-right">
        <span style="margin-right: 10px">
          <span>属性冲突解决规则：</span>
          <span v-if="fusionStatus === 1">{{ resolutionRule.name }}</span>
          <el-select v-else v-model="fusionRuleId" size="small">
            <el-option
              v-for="i in fusionRules"
              :key="i.id"
              :label="i.name"
              :value="i.id"
            ></el-option>
          </el-select>
        </span>

        <el-button
          v-if="fusionStatus === 0"
          size="small"
          type="primary"
          @click="executeMerge"
          >执行融合</el-button
        >
        <el-button size="small" type="primary" @click="$router.go(-1)">
          返回
        </el-button>
      </div>
    </div>
    <div class="merge-main" v-if="Object.keys(fusionData).length">
      <!-- 实体信息 -->
      <div class="ontology-info">
        <div class="info-top">
          <div class="info-name bold-text">{{ clashEntityInfo.value }}</div>
          <div
            class="clash-wrap"
            v-if="clashEntityInfo.isClash"
            @click="confirmFusion()"
          >
            {{ clashEntityInfo.warnInfo }}
          </div>
        </div>
        <div class="info-attr">
          <span class="attr-label">所属类别：</span>
          <span class="attr-label">{{ fusionData.ontologyName || "---" }}</span>
        </div>
        <div class="info-attr">
          <span class="attr-label">消歧标识：</span>
          <span class="attr-content">{{
            fusionData.disambiguationSigns || "---"
          }}</span>
        </div>
      </div>
      <!-- 属性信息 -->
      <div class="attributes-info">
        <div class="attr-top">
          <div class="attr-title bold-text">属性</div>
          <el-checkbox v-model="hideNoClash">隐藏无冲突数据</el-checkbox>
        </div>

        <template v-for="(val, k, idx) in attributesInfo">
          <div
            class="attr-item"
            :key="idx"
            v-if="(hideNoClash && isClashAttr(k)) || !hideNoClash"
          >
            <div class="clash-warning">
              <i class="el-icon-warning" v-if="isClashAttr(k)"></i>
            </div>
            <div class="attr-item-main">
              <span class="attr-label">{{ k }}：</span>
              <span class="attr-content">
                <template v-if="isClashAttr(k)">
                  {{ getAttrClashInfo(k).value }}
                </template>
                <template v-else>
                  {{ val }}
                </template>
              </span>
            </div>
            <div
              class="clash-wrap"
              v-if="isClashAttr(k)"
              @click="confirmFusion(k)"
            >
              {{ getAttrClashInfo(k).warnInfo }}
            </div>
          </div>
        </template>
      </div>
    </div>
    <!-- 全部待融合实体 -->
    <PendingFused ref="pendingFusedRef" @reload="getFusionDetail" />
    <!-- 确认结果 -->
    <el-dialog
      :title="dialogTitle"
      :visible.sync="dialogVisible"
      width="35%"
      @closed="afterCloseDialog"
    >
      <div class="fusion-content">
        <div class="info-attr bold-text" style="margin-bottom: 20px">
          <span class="attr-label">融合项：</span>
          <span class="attr-content">{{ curFusionItem.name }}</span>
        </div>
        <div>存在以下{{ curFusionItem.data.length }}项冲突值：</div>
        <div
          class="radio-item"
          v-for="(r, idx) in curFusionItem.data"
          :key="idx"
        >
          <el-radio
            v-model="curFusionItem.chooseIdx"
            :disabled="fusionStatus === 1 || fusionStatus === 2"
            :label="idx"
            >{{ r.value }}</el-radio
          >
          <div class="clash-wrap">
            <template v-if="currentFusionRuleType === 1">
              [相同值共{{ r.count }}个]
            </template>
            <template v-else-if="currentFusionRuleType === 2">
              [置信度 {{ r.confidence * 100 }}%]
            </template>
            <template v-else-if="currentFusionRuleType === 3">
              [更新时间：{{ formatTime(r.updateTime) }}]
            </template>
          </div>
        </div>
        <div
          class="custom-info"
          v-if="fusionStatus === 0 || fusionStatus === 1"
        >
          <div class="radio-item">
            <el-radio
              v-model="curFusionItem.chooseIdx"
              :disabled="fusionStatus === 1"
              :label="-1"
            >
              自定义
            </el-radio>
            <div class="clash-wrap info">[可输入与上述属性值不同的任何值]</div>
          </div>
          <div class="custom-input">
            <el-input
              v-model="curFusionItem.custom"
              :disabled="fusionStatus === 1 || curFusionItem.chooseIdx !== -1"
            ></el-input>
          </div>
        </div>
      </div>
      <template #footer v-if="fusionStatus === 0">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmDialog">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script>
import PendingFused from "./components/PendingFused.vue";
import { mockData } from "./mock";
import cloneDeep from "lodash/cloneDeep";
import dayjs from "dayjs";
export default {
  name: "KnowledgeFusionDetail",
  components: {
    PendingFused,
  },
  data() {
    return {
      pageTitle: "融合结果",
      fusionRules: [], // 融合规则
      fusionRuleId: null, // 当前融合规则ID
      fusionRuleName: null, // 当前融合规则名称(用于已融合查看用)
      fusionData: {}, // 请求得到的数据
      // 转换后的实体名称冲突信息
      entityNameInfo: {
        isClash: false,
      },
      // 转换后的实体属性冲突信息
      attributesInfo: {},

      // 隐藏无冲突项
      hideNoClash: false,

      // dialog
      dialogTitle: "确认结果",
      dialogVisible: false,
      curFusionItem: {
        name: null,
        data: [],
        chooseIdx: null,
        custom: null,
        // 标识是否是实体名称 name判断可能和属性名冲突
        isEntityName: true,
      },
    };
  },
  computed: {
    // 实体展示信息
    clashEntityInfo() {
      if (this.currentFusionRuleType === 1) {
        let tmp = this.entityNameInfo["1"][0];
        return {
          value: tmp.value,
          isClash: this.entityNameInfo.isClash,
          warnInfo: `[相同值共${tmp.count || 0}个]`,
        };
      } else if (this.currentFusionRuleType === 2) {
        let tmp = this.entityNameInfo["2"][0];
        return {
          value: tmp.value,
          isClash: this.entityNameInfo.isClash,
          warnInfo: `[置信度 ${tmp.confidence * 100}%]`,
        };
      } else if (this.currentFusionRuleType === 3) {
        let tmp = this.entityNameInfo["3"][0];
        return {
          value: tmp.value,
          isClash: this.entityNameInfo.isClash,
          warnInfo: `[更新时间：${this.formatTime(tmp.updateTime)}]`,
        };
      } else {
        return {
          value: "",
          isClash: false,
        };
      }
    },
    // 当前选择规则
    currentFusionRule() {
      return this.fusionRules.find((i) => i.id === this.fusionRuleId);
    },
    // 当前选择规则类型
    currentFusionRuleType() {
      if (this.currentFusionRule) {
        return this.currentFusionRule.ruleCondition;
      }
      return 1;
    },
    // 当前规则详情 用于已融合查看用
    resolutionRule() {
      return this.fusionData.resolutionRule || {};
    },
    // 数据状态 0-未融合，1-已融合，2-已取消
    fusionStatus() {
      return Number.isInteger(this.fusionData.status)
        ? this.fusionData.status
        : 2;
    },
  },
  created() {
    this.getFusionDetail();
  },
  methods: {
    // 融合详情
    getFusionDetail() {
      // try {
      //   mockData.entityName = JSON.parse(mockData.entityName);
      //   mockData.attributes = JSON.parse(mockData.attributes);
      //   mockData.originalData = JSON.parse(mockData.originalData);
      //   mockData.resolutionRule = JSON.parse(mockData.resolutionRule);
      // } catch (error) {
      //   console.error("数据解析失败");
      // }
      // this.fusionData = mockData;
      // this.transClashInfo();
      // this.getFusionRules();
      this.$axios
        .get(this.$api.knowledgeComputation.knowledgeFusion.fusionDetail, {
          params: { id: this.$route.query.id },
        })
        .then((res) => {
          const { data, message, code } = res.data;
          if (code === 200) {
            try {
              data.entityName = JSON.parse(data.entityName);
              data.attributes = JSON.parse(data.attributes);
              data.originalData = JSON.parse(data.originalData);
              data.resolutionRule = JSON.parse(data.resolutionRule);
            } catch (error) {
              console.error("数据解析失败");
            }
            this.fusionData = data;
            this.transClashInfo();
            // 未融合 已取消时请求列表
            this.getFusionRules();
          } else {
            this.$message.warning(message);
          }
        })
        .catch((err) => {
          this.$message.error("请求失败");
        });
    },
    // 融合规则列表
    getFusionRules() {
      this.$axios
        .get(this.$api.knowledgeComputation.fusionRule.getFusionRuleList, {
          params: { pageNum: 1, pageSize: 100 },
        })
        .then((res) => {
          const { data, message, code } = res.data;
          if (code === 200) {
            if (Array.isArray(data.list) && data.list.length) {
              this.fusionRules = data.list;
              // 已融合状态时 id使用后台返回值 否则第一项
              if (this.fusionStatus === 1) {
                this.fusionRuleId = this.resolutionRule.id;
              } else {
                this.fusionRuleId = data.list[0].id;
              }
            }
          } else {
            this.$message.warning(message);
          }
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // 转换冲突信息
    transClashInfo() {
      // 实体名称
      if (this.fusionData.entityName.length === 1) {
        let tmpObj = cloneDeep(this.fusionData.entityName);
        this.entityNameInfo = {
          isClash: false,
          1: tmpObj,
          2: tmpObj,
          3: tmpObj,
        };
      } else if (this.fusionData.entityName.length > 1) {
        this.entityNameInfo = {
          isClash: true,
          ...this.makeResByRuleCondition(this.fusionData.entityName),
        };
      }

      // 实体属性
      const res = {};
      for (let k in this.fusionData.attributes) {
        let val = this.fusionData.attributes[k];
        if (Array.isArray(val)) {
          res[k] = this.makeResByRuleCondition(val);
        } else {
          res[k] = val;
        }
      }
      this.attributesInfo = res;
    },
    // 生成不同规则类型的结果
    makeResByRuleCondition(arr) {
      const clashMap = { 1: {}, 2: {}, 3: {} };
      arr.forEach((item) => {
        if (item.value in clashMap["1"]) {
          clashMap["1"][item.value].count++;
          if (item.choose) {
            clashMap["1"][item.value].choose = item.choose;
          }
          if (item.customize) {
            clashMap["1"][item.value].customize = item.customize;
          }
        } else {
          clashMap["1"][item.value] = { ...item, count: 1 };
        }
        if (!(item.confidence in clashMap["2"])) {
          clashMap["2"][item.confidence] = { ...item };
        }
        if (!(item.updateTime in clashMap["3"])) {
          clashMap["3"][item.updateTime] = { ...item };
        }
      });
      // 数量排序
      let countSort = Object.values(clashMap["1"]);
      countSort.sort((a, b) => b.count - a.count);
      // 置信度排序
      let confidenceSort = Object.values(clashMap["2"]);
      confidenceSort.sort((a, b) => b.confidence - a.confidence);
      // 时间排序
      let timeSort = Object.values(clashMap["3"]);
      timeSort.sort((a, b) => b.updateTime - a.updateTime);
      return {
        1: countSort,
        2: confidenceSort,
        3: timeSort,
      };
    },
    // 全部待融合实体
    showPending() {
      this.$refs.pendingFusedRef.openDialog(cloneDeep(this.fusionData));
    },
    // 是否是冲突属性
    isClashAttr(key) {
      let tmpAttr = this.attributesInfo[key];
      if (
        typeof tmpAttr === "object" &&
        "1" in tmpAttr &&
        "2" in tmpAttr &&
        "3" in tmpAttr
      ) {
        return true;
      } else {
        return false;
      }
    },
    // 获取冲突项展示信息
    getAttrClashInfo(key) {
      let tmpArr = this.attributesInfo[key];
      if (this.currentFusionRuleType === 1) {
        let tmp = tmpArr["1"][0];
        return {
          value: tmp.value,
          warnInfo: `[相同值共${tmp.count || 0}个]`,
        };
      } else if (this.currentFusionRuleType === 2) {
        let tmp = tmpArr["2"][0];
        return {
          value: tmp.value,
          warnInfo: `[置信度 ${tmp.confidence * 100}%]`,
        };
      } else if (this.currentFusionRuleType === 3) {
        let tmp = tmpArr["3"][0];
        return {
          value: tmp.value,
          warnInfo: `[更新时间：${this.formatTime(tmp.updateTime)}]`,
        };
      } else {
        return {
          value: "",
        };
      }
    },
    // 转换时间
    formatTime(time) {
      return dayjs(time).format("YYYY-MM-DD HH:mm:ss");
    },
    // 确认结果
    confirmFusion(key) {
      if (key) {
        this.curFusionItem.name = key;
        this.curFusionItem.data =
          cloneDeep(this.attributesInfo[key][this.currentFusionRuleType]) || [];
        this.curFusionItem.isEntityName = false;
      } else {
        this.curFusionItem.name = "实体名称";
        this.curFusionItem.data =
          cloneDeep(this.entityNameInfo[this.currentFusionRuleType]) || [];
        this.curFusionItem.isEntityName = true;
      }
      // 如果存在被选择项 回显
      let existChoose = this.curFusionItem.data.findIndex(
        (i) => i.choose === 1
      );
      if (existChoose !== -1) {
        this.curFusionItem.chooseIdx = existChoose;
      }
      // 如果存在自定义项 回显
      let existCustom = this.curFusionItem.data.findIndex(
        (i) => i.customize === 1
      );
      if (existCustom !== -1) {
        this.curFusionItem.chooseIdx = -1;
        const delArr = this.curFusionItem.data.splice(existCustom, 1);
        this.curFusionItem.custom = delArr[0].value;
      }
      this.dialogVisible = true;
    },
    afterCloseDialog() {
      this.curFusionItem = {
        name: null,
        data: [],
        chooseIdx: null,
        custom: null,
        isEntityName: true,
      };
    },
    confirmDialog() {
      if (this.curFusionItem.chooseIdx === null) {
        this.dialogVisible = false;
        return;
      }
      const copyFusionItem = cloneDeep(this.curFusionItem);
      if (copyFusionItem.chooseIdx === -1) {
        if (!copyFusionItem.custom) {
          return this.$message.warning("请填写自定义值");
        } else {
          copyFusionItem.data.push({
            value: copyFusionItem.custom,
            customize: 1,
          });
        }
      } else {
        copyFusionItem.data[copyFusionItem.chooseIdx].choose = 1;
      }
      // 更新融合数据项的值
      if (copyFusionItem.isEntityName) {
        this.entityNameInfo[this.currentFusionRuleType] = copyFusionItem.data;
      } else {
        this.attributesInfo[copyFusionItem.name][this.currentFusionRuleType] =
          copyFusionItem.data;
      }
      this.dialogVisible = false;
    },
    // 执行融合时 更新提交数据
    updateSubmitData() {
      // 实体
      let entityData = this.entityNameInfo[this.currentFusionRuleType];
      // 选择项
      let existChoose = entityData.find((i) => i.choose === 1);
      if (existChoose) {
        let entityIdx = this.fusionData.entityName.findIndex(
          (i) => i.value === existChoose.value
        );
        if (entityIdx !== -1) {
          this.$set(this.fusionData.entityName[entityIdx], "choose", 1);
        }
      }
      // 自定义
      let existCustom = entityData.find((i) => i.customize === 1);
      if (existCustom) {
        this.fusionData.entityName.push(existCustom);
      }

      // 属性
      for (let k in this.attributesInfo) {
        if (this.isClashAttr(k)) {
          let tmpArrData = this.attributesInfo[k][this.currentFusionRuleType];
          // 选择项
          let attrChoose = tmpArrData.find((i) => i.choose === 1);
          if (attrChoose) {
            let attrIdx = this.fusionData.attributes[k].findIndex(
              (i) => i.value === attrChoose.value
            );
            if (attrIdx !== -1) {
              this.$set(this.fusionData.attributes[k][attrIdx], "choose", 1);
            }
          }
          // 自定义
          let attrCustom = tmpArrData.find((i) => i.customize === 1);
          if (attrCustom) {
            this.fusionData.attributes[k].push(attrCustom);
          }
        }
      }
    },
    executeMerge() {
      this.updateSubmitData();
      // 获取数据
      this.$axios
        .post(this.$api.knowledgeComputation.knowledgeFusion.executeFusion, {
          fusionRuleId: this.fusionRuleId,
          knowledgeFusion: {
            ...this.fusionData,
            entityName: JSON.stringify(this.fusionData.entityName),
            attributes: JSON.stringify(this.fusionData.attributes),
            originalData: JSON.stringify(this.fusionData.originalData),
            resolutionRule: JSON.stringify(this.fusionData.resolutionRule),
          },
        })
        .then((res) => {
          const { data, message, code } = res.data;
          if (code === 200) {
            this.$message.success(message);
            this.$router.go(-1);
          } else {
            this.$message.warning(message);
          }
        })
        .catch((err) => {
          console.log(err);
          // 操作失败重新请求数据 以清空当前设置项
          this.getFusionDetail();
        });
    },
  },
};
</script>
<style lang="scss" scoped>
.merge-result {
  background: #fff;
}

.merge-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  padding: 12px 32px;
  border-bottom: 1px solid #ddd;
  .head-left {
    display: flex;
    align-items: center;
  }
  .head-title {
    font-size: 16px;
    font-weight: bold;
    margin-right: 20px;
    width: max-content;
  }
}
.merge-main {
  padding: 32px;
}

.ontology-info {
  .info-top {
    display: flex;
    justify-content: space-between;
  }
}
.bold-text {
  font-weight: 700;
  font-size: 18px;
  width: max-content;
}
.clash-wrap {
  color: #e6a23c;
  cursor: pointer;
  &.info {
    color: #909399;
  }
}

.info-attr {
  font-size: 14px;
  color: #777;
  margin: 7px 0;
}

.attr-top {
  display: flex;
  justify-content: space-between;
  margin: 20px 0 10px;
  padding-bottom: 5px;
  border-bottom: 1px solid #e5e5e5;
}

.attr-item {
  display: flex;
  align-items: center;
  margin: 15px 0;
  .attr-item-main {
    flex: 1;
  }
  .clash-warning {
    width: 25px;
  }
  .el-icon-warning {
    color: #e6a23c;
    font-size: 18px;
  }
}

.attr-label {
  width: max-content;
}

/deep/ .el-dialog__body {
  padding: 10px 20px;
}

.radio-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 10px;
}
.custom-input {
  margin: 10px;
  width: 50%;
}
</style>
